using UnityEngine;
using UnityEngine.UI;

namespace GameFrameWork
{

    [DisallowMultipleComponent]
    public abstract class UIBaseMesh : BaseMeshEffect
    {
        public sealed override void ModifyMesh(VertexHelper vh)
        {
            if (graphic)
            {
                GetUV(graphic, out var outBound, out var outUV, out var outColor);
                OnModifyMesh(vh, ref outBound, ref outUV, ref outColor);
            }
        }

        protected virtual void OnModifyMesh(VertexHelper vh, ref Vector4 outBound, ref Vector4 outUV, ref Color outColor) { }


        static bool GetUV(Graphic g, out Vector4 outBound, out Vector4 outUV, out Color outColor)
        {
            if (g is Image image)
            {
                if (image.sprite != null)
                {
                    outBound = GetDrawingDimensions(image, image.preserveAspect);
                    outUV = UnityEngine.Sprites.DataUtility.GetOuterUV(image.sprite);
                }
                else
                {
                    var r = image.GetPixelAdjustedRect();
                    outBound = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
                    outUV = new Vector4(0f, 0f, 1f, 1f);
                }
                outColor = image.color;
                return true;
            }
            else if (g is RawImage rawImage)
            {
                var uvRect = rawImage.uvRect;
                var tex = rawImage.mainTexture;
                var r = rawImage.GetPixelAdjustedRect();
                var scaleX = tex.width * tex.texelSize.x;
                var scaleY = tex.height * tex.texelSize.y;

                outBound = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
                outUV = new Vector4(uvRect.xMin * scaleX, uvRect.yMin * scaleY, uvRect.xMax * scaleX, uvRect.yMax * scaleY);
                outColor = rawImage.color;
                return true;
            }
            else
            {
                outBound = Vector4.zero;
                outColor = Color.clear;
                outUV = Vector4.zero;
                return false;
            }
        }

        static Vector4 GetDrawingDimensions(Image image, bool shouldPreserveAspect)
        {
            var padding = image.sprite == null
                ? Vector4.zero
                : UnityEngine.Sprites.DataUtility.GetPadding(image.sprite);
            var size = image.sprite == null
                ? Vector2.zero
                : new Vector2(image.sprite.rect.width, image.sprite.rect.height);

            Rect r = image.GetPixelAdjustedRect();
            int spriteW = Mathf.RoundToInt(size.x);
            int spriteH = Mathf.RoundToInt(size.y);

            var v = new Vector4(
                padding.x / spriteW,
                padding.y / spriteH,
                (spriteW - padding.z) / spriteW,
                (spriteH - padding.w) / spriteH);

            if (shouldPreserveAspect && size.sqrMagnitude > 0.0f)
            {
                PreserveSpriteAspectRatio(ref r, size, image.rectTransform);
            }

            v = new Vector4(
                r.x + r.width * v.x,
                r.y + r.height * v.y,
                r.x + r.width * v.z,
                r.y + r.height * v.w
            );
            return v;
        }
        static void PreserveSpriteAspectRatio(ref Rect rect, Vector2 spriteSize, RectTransform rectTransform)
        {
            var spriteRatio = spriteSize.x / spriteSize.y;
            var rectRatio = rect.width / rect.height;

            if (spriteRatio > rectRatio)
            {
                var oldHeight = rect.height;
                rect.height = rect.width * (1.0f / spriteRatio);
                rect.y += (oldHeight - rect.height) * rectTransform.pivot.y;
            }
            else
            {
                var oldWidth = rect.width;
                rect.width = rect.height * spriteRatio;
                rect.x += (oldWidth - rect.width) * rectTransform.pivot.x;
            }
        }
    }
}
